home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 335_04 / frapsub.c < prev    next >
C/C++ Source or Header  |  1990-12-02  |  22KB  |  1,117 lines

  1. /*
  2. HEADER:     ;
  3. TITLE:         Frankenstein Cross Assemblers;
  4. VERSION:     2.0;
  5. DESCRIPTION: "    Reconfigurable Cross-assembler producing Intel (TM)
  6.         Hex format object records.  ";
  7. SYSTEM:     UNIX, MS-Dos ;
  8. FILENAME:     frapsub.c ;
  9. WARNINGS:     "This software is in the public domain.  
  10.         Any prior copyright claims are relinquished.  
  11.  
  12.         This software is distributed with no warranty whatever.  
  13.         The author takes no responsibility for the consequences 
  14.         of its use.  "  ;
  15. SEE-ALSO:     frasmain.c;
  16. AUTHORS:     Mark Zenier;
  17. */
  18.  
  19. /*
  20.     description    Parser phase utility routines
  21.     History        September 1987
  22.             September 14, 1990 Dosify, 6 char unique names
  23. */
  24.  
  25. #include "fragcon.h"
  26. #include <stdio.h>
  27. #include "frasmdat.h"
  28.  
  29. #define STRALLOCSZ 4096
  30.  
  31.     local char *currstr;
  32.  
  33. char * savestring(stx, len)
  34.     char *stx;
  35.     int len;
  36. /*
  37.     description    save a character string in permanent (interpass) memory
  38.     parameters    the string and its length
  39.     globals     the string pool
  40.     return        a pointer to the saved string
  41. */
  42. {
  43.     char * rv;
  44.     static int savestrleft = 0;
  45.  
  46.     if( savestrleft < (len+1))
  47.     {
  48.         if((currstr = malloc(STRALLOCSZ)) == (char *)NULL)
  49.         {
  50.             frafatal("cannot allocate string storage");
  51.         }
  52.         savestrleft = STRALLOCSZ;
  53.     }
  54.  
  55.     savestrleft -= (len+1);
  56.  
  57.     rv = currstr;
  58.     for(; len > 0; len--)
  59.         *currstr++ = *stx++;
  60.     *currstr++ = '\0';
  61.  
  62.     return rv;
  63. }
  64.  
  65. /* expression node operations */
  66.  
  67. /* expression tree element */
  68. struct etelem
  69. {
  70.     int    evs;
  71.     int    op;
  72.     int    left, right;
  73.     long    val;
  74.     struct symel *sym;
  75. };
  76.  
  77. #define NUMENODE INBUFFSZ
  78. struct etelem enode[NUMENODE];
  79.  
  80. local int nextenode = 1;
  81.  
  82. /* non general, one exprlist or stringlist per line */
  83. int nextexprs = 0;
  84. int nextstrs = 0;
  85.  
  86. clrexpr()
  87. /*
  88.     description    clear out the stuff used for each line
  89.             the temporary string pool
  90.             the expression tree storage pool
  91.             the string and expression lists
  92. */
  93. {
  94.     nextenode = 1;
  95.     nextexprs = nextstrs = 0;
  96. }
  97.  
  98. exprnode(swact, left, op, right, value, symbol)
  99.     int swact, left, op, right;
  100.     long value;
  101.     struct symel * symbol;
  102. /*
  103.     description    add an element to the expression tree pool
  104.     parameters    swact, the action performed by the switch in
  105.                 the polish conversion routine, the category
  106.                 of the expression node.
  107.             left, right  the subscripts of the decendent nodes
  108.                     of the expression tree element
  109.             op, the operation to preform
  110.             value, a constant value (maybe)
  111.             symbol, a pointer to a symbol element (maybe)
  112.     globals        the next available table element
  113.     return        the subscript of the expression node
  114. */
  115. {
  116.     if(nextenode >= NUMENODE)
  117.     {
  118.         frafatal("excessive number of subexpressions");
  119.     }
  120.  
  121.     enode [nextenode].evs = swact;
  122.     enode [nextenode].left = left;
  123.     enode [nextenode].op = op;
  124.     enode [nextenode].right = right;
  125.     enode [nextenode].val = value;
  126.     enode [nextenode].sym = symbol;
  127.  
  128.     return nextenode ++;
  129. }
  130.  
  131. int nextsymnum = 1;
  132.  
  133. local struct symel *syallob;
  134. #define SYELPB 512
  135. local int nxtsyel = SYELPB;
  136.  
  137. struct symel *allocsym()
  138. /*
  139.     description    allocate a symbol table element, and allocate
  140.             a block if the current one is empty.  A fatal
  141.             error if no more space can be gotten
  142.     globals        the pointer to the current symbol table block
  143.             the count of elements used in the block
  144.     return        a pointer to the symbol table element
  145. */
  146. {
  147.  
  148.     if(nxtsyel >= SYELPB)
  149.     {
  150.         if( (syallob = (struct symel *)calloc(
  151.             SYELPB , sizeof(struct symel)))
  152.          == (struct symel *)NULL)
  153.         {
  154.             frafatal("cannot allocate symbol space");
  155.         }
  156.  
  157.         nxtsyel = 0;
  158.     }
  159.  
  160.     return &syallob[nxtsyel++];
  161. }
  162.  
  163.  
  164. #define SYHASHOFF 13
  165. #define SYHASHSZ 1023
  166.  
  167. int syhash(str)
  168.     register char *str;
  169. /*
  170.     description    produce a hash index from a character string for
  171.             the symbol table.
  172.     parameters     a character string
  173.     return        an integer related in some way to the character string
  174. */
  175. {
  176.     unsigned rv = 0;
  177.     register int offset = 1;
  178.     register int c;
  179.  
  180.     while((c = *(str++)) > 0)
  181.     {
  182.         rv += (c - ' ') * offset;
  183.         offset *= SYHASHOFF;
  184.     }
  185.  
  186.     return rv % SYHASHSZ;
  187. }
  188.  
  189. local struct symel * (shashtab[SYHASHSZ]);
  190.  
  191. static struct symel *getsymslot(str)
  192.     char * str;
  193. /*
  194.     description    find an existing symbol in the symbol table, or
  195.             allocate an new element if the symbol doen't exist.
  196.             action: hash the string
  197.                 if there are no symbols for the hash value
  198.                     create one for this string
  199.                 otherwise
  200.                 scan the linked list until the symbol is 
  201.                 found or the end of the list is found
  202.                 if the symbol was found
  203.                     exit
  204.                 if the symbol was not found, allocate and
  205.                 add at the end of the linked list
  206.                 fill out the symbol
  207.     parameters    the character string 
  208.     globals        all the symbol table
  209.     return        a pointer to the symbol table element for this
  210.             character string
  211. */
  212. {
  213.     struct symel *currel, *prevel;
  214.     int hv;
  215.  
  216.     if( (currel = shashtab[hv = syhash(str)])
  217.         == (struct symel *)NULL)
  218.     {
  219.         shashtab[hv] = currel = allocsym();
  220.     }
  221.     else
  222.     {
  223.         do  {
  224.             if(strcmp(currel -> symstr, str) == 0)
  225.             {
  226.                 return currel;
  227.             }
  228.             else
  229.             {
  230.                 prevel = currel;
  231.                 currel = currel -> nextsym;
  232.             }
  233.         } while( currel != (struct symel *)NULL);
  234.  
  235.         prevel -> nextsym = currel = allocsym();
  236.     }
  237.  
  238.     currel -> symstr = savestring(str, strlen(str));
  239.     currel -> nextsym = (struct symel *)NULL;
  240.     currel -> tok = 0;
  241.     currel -> value = 0;
  242.     currel -> seg = SSG_UNUSED;
  243.  
  244.     return currel;
  245. }
  246.  
  247. struct symel * symbentry(str,toktyp)
  248.     char * str;
  249.     int toktyp;
  250. /*
  251.     description    find or add a nonreserved symbol to the symbol table
  252.     parameters    the character string
  253.             the syntactic token type for this charcter string
  254.                 (this is a parameter so the routine doesn't
  255.                 have to be recompiled since the yacc grammer
  256.                 provides the value)
  257.     globals        the symbol table in all its messy glory
  258.     return        a pointer to the symbol table element
  259. */
  260. {
  261.     struct symel * rv;
  262.  
  263.     rv = getsymslot(str);
  264.  
  265.     if(rv -> seg == SSG_UNUSED)
  266.     {
  267.         rv -> tok = toktyp;
  268.         rv -> symnum = nextsymnum ++;
  269.         rv -> seg = SSG_UNDEF;
  270.     }
  271.  
  272.     return rv;
  273. }
  274.  
  275. void reservedsym(str, tok, value)
  276.     char * str;
  277.     int tok;
  278.     int value;
  279. /*
  280.     description    add a reserved symbol to the symbol table.
  281.     parameters    the character string, must be a constant as
  282.             the symbol table does not copy it, only point to it.
  283.             The syntactic token value.
  284.             The associated value of the symbol.
  285. */
  286. {
  287.     struct symel * tv;
  288.  
  289.     tv = getsymslot(str);
  290.  
  291.     if(tv -> seg != SSG_UNUSED)
  292.     {
  293.         frafatal("cannot redefine reserved symbol");
  294.     }
  295.  
  296.     tv -> symnum = 0;
  297.     tv -> tok = tok;
  298.     tv -> seg = SSG_RESV;
  299.     tv -> value = value;
  300.  
  301. }
  302.  
  303. buildsymbolindex()
  304. /*
  305.     description    allocate and fill an array that points to each
  306.             nonreserved symbol table element, used to reference
  307.             the symbols in the intermediate file, in the output
  308.             pass.
  309.     globals        the symbol table
  310. */
  311. {
  312.     int hi;
  313.     struct symel *curr;
  314.  
  315.     if((symbindex = (struct symel **)calloc((unsigned)nextsymnum, 
  316.             sizeof (struct symel *))) == (struct symel **)NULL)
  317.     {
  318.         frafatal(" unable to allocate symbol index");
  319.     }
  320.  
  321.     for(hi = 0; hi < SYHASHSZ; hi++)
  322.     {
  323.         if( (curr = shashtab[hi]) != SYMNULL)
  324.         {
  325.             do  {
  326.                 if( curr -> symnum)
  327.                     symbindex[curr -> symnum] = curr;
  328.  
  329.                 curr = curr -> nextsym;
  330.             }  while(curr != SYMNULL);
  331.         }
  332.     }
  333. }
  334.  
  335. /* opcode symbol table */
  336.  
  337. #define OPHASHOFF 13
  338. #define OPHASHSZ 1023
  339.  
  340. local int ohashtab[OPHASHSZ];
  341.  
  342. setophash()
  343. /*
  344.     description    set up the linked list hash table for the
  345.             opcode symbols 
  346.     globals        the opcode hash table
  347.             the opcode table
  348. */
  349. {
  350.     int opn, pl, hv;
  351.  
  352.         /* optab[0] is reserved for the "invalid" entry */
  353.         /*  opcode subscripts range from 0 to numopcode - 1 */
  354.     for(opn = 1; opn < gnumopcode; opn++)
  355.     {
  356.         hv = opcodehash(optab[opn].opstr);
  357.  
  358.         if( (pl = ohashtab[hv]) == 0)
  359.         {
  360.             ohashtab[hv] = opn;
  361.         }
  362.         else
  363.         {
  364.             while( ophashlnk[pl] != 0)
  365.             {
  366.                 pl = ophashlnk[pl];
  367.             }
  368.  
  369.             ophashlnk[pl] = opn;
  370.             ophashlnk[opn] = 0;
  371.         }
  372.     }
  373. }
  374.  
  375.  
  376. int findop(str)
  377.     char *str;
  378. /*
  379.     description    find an opcode table subscript
  380.     parameters    the character string
  381.     globals        the opcode hash linked list table
  382.             the opcode table
  383.     return